package math.random;

import java.util.Random;

/**
 * Fully Documented: Yes
 * Tested: Yes
 * 
 * @author Shimu
 * @date 12-Jul-2012
 */
public class NonRepeatingRandomGenerator {

    private final int[] values;
    private int size;
    private final Random random;

    /**
     * Instantiates an integer random number generator that generates distinct
     * integers within the given range (inclusive). 
     * @param min
     * @param max 
     */
    public NonRepeatingRandomGenerator(int min, int max) {
        // Create an array with all the possible values
        this.size = max - min + 1;
        this.values = new int[size];
        for (int i = 0; i < size; i++) {
            values[i] = min + i;
        }

        this.random = new Random();
    }

    /**
     * Removes a value at the given index from the array of values. The removed
     * value is replaced with the value at the end of the array. Size is 
     * decremented and the original value at the given index is returned.
     * 
     * @param index the index of the value in the array
     * @return 
     */
    private int pop(int index) {
        int returnValue = values[index];
        values[index] = values[size - 1];
        size--;
        return returnValue;
    }

    /**
     * Generates a random number that is within the range (inclusive) given to 
     * the constructor and different from all the values returned by previous
     * calls to generate. If there are no more distinct values left in the
     * range, 0 is returned.
     * 
     * @return 
     */
    public int generate() {
        if (size == 0) {
            return 0;
        }
        return pop(random.nextInt(size));
    }
}
